package com.example.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.common.result.Result;
import com.example.config.RedisCache;
import com.example.controller.CmsmgController;
import com.example.entity.dto.FileUpload.FileListDto;
import com.example.entity.dto.User.MyUser;
import com.example.entity.excel.MyRowWriteHandler;
import com.example.entity.excel.SaleExcel;
import com.example.entity.mes.File;
import com.example.entity.money.RaxDto;
import com.example.entity.money.RaxVo;
import com.example.entity.pojo.MqunitPage;
import com.example.entity.yifei.*;
import com.example.entity.ymlConfig.YmlConfig;
import com.example.exception.CustomException;
import com.example.mapper.*;
import com.example.service.CmsmqService;
import com.example.service.FileService;
import com.example.untils.*;
import com.github.houbb.opencc4j.util.ZhTwConverterUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.CompletableFuture;

@Service
@Log4j2
public class FileServiceImpl implements FileService {

    @Autowired
    private CmsmqService cmsmqService;

    @Autowired
    private AttachMapper attachMapper;

    @Autowired
    private CopmgMapper copmgMapper;

    @Autowired
    private CoptbMapper coptbMapper;

    @Autowired
    private CopmaMapper copmaMapper;

    @Autowired
    private InvmbMapper invmbMapper;

    @Autowired
    private CmsmfMapper cmsmfMapper;

    @Autowired
    private CoptcMapper coptcMapper;

    @Autowired
    private CoptdMapper coptdMapper;

    @Autowired
    private CmsmvMapper cmsmvMapper;

    @Autowired
    private CmsmeMapper cmsmeMapper;

    @Autowired
    private CmsnaMapper cmsnaMapper;

    @Autowired
    private CmsmcMapper cmsmcMapper;

    @Autowired
    private CmsmgController cmsmgController;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private FileMapper fileMapper;

    @Resource
    private CopmdMapper copmdMapper;


    @Override
    public Result insert(File file) {
        try{
            LambdaQueryWrapper<File> fileLambdaQueryWrapper = new LambdaQueryWrapper<>();
            fileLambdaQueryWrapper.eq(File::getCode, file.getCode());
            File file1 = this.fileMapper.selectOne(fileLambdaQueryWrapper);
            if (file1!=null){
                return Result.error("此员工已添加签章!");
            }
            int insert = this.fileMapper.insert(file);
            if (insert>0){
                return Result.success("新增成功");
            }
            return Result.error("文件新增失败");
        }catch (Exception e){
            return Result.error("文件新增发生异常"+e);
        }
    }


    @Override
    public Result update(File file) {
        try {
            int update = this.fileMapper.updateById(file);
            if (update > 0) {
                return Result.success("修改成功");
            }
            return Result.error("修改失败");
        } catch (Exception e) {
            return Result.error("修改发生异常" + e);
        }
    }

    @Override
    public Result delete(Long id) {
        try{
            int i = this.fileMapper.deleteById(id);
            if (i>0){
                return Result.success("删除成功");
            }
            return Result.error("删除错误,请输入正确的id");
        }catch (Exception e){
            throw new CustomException("500","异常");
        }
    }

    @Override
    public Result queryPageList(MqunitPage mqunitPage) {
        try{
            Map<String,Object> map = new HashMap<>();
            IPage<File> page = new Page<>(mqunitPage.getCurrent(), mqunitPage.getSize());
            IPage<File> fileIPage = this.fileMapper.selectPage(page, null);
            if (!fileIPage.getRecords().isEmpty()){
                map.put("page", fileIPage.getPages());
                map.put("total", fileIPage.getTotal());
                map.put("data", fileIPage.getRecords());
                return Result.success(map);
            }
            return Result.error("文件分页查询暂无数据");
        }catch (Exception e){
            return Result.error("文件分页查询发生异常"+e);
        }
    }

    @Override
    public Result<File> queryById(Long id) {
        try{
            File file = this.fileMapper.selectById(id);
            if (file!=null){
                return Result.success(file);
            }
            return Result.error("通过id查询暂时没有数据");
        }catch (Exception e){
            return Result.error("通过id查询发生异常"+e);
        }
    }

    @Override
    public Result queryCodeSign(List<String> codes) {
        List<File> files = this.fileMapper.queryCodeSign(codes);
        return Result.success(files);
    }


    public boolean isExcelFileByMime(MultipartFile file) {
        String contentType = file.getContentType();
        return "application/vnd.ms-excel".equals(contentType) ||
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(contentType);
    }

    public SaleExcel convertToSimplifiedChinese(SaleExcel saleExcel) {
        // 创建 OpenCC 转换器，选择繁体到简体
        //反射，Declared 获取改类所有的字段
        Field[] fields = saleExcel.getClass().getDeclaredFields();
        //遍历所有的字段
        for(Field field : fields) {
            //可访问所有对象包括私有的字段
            field.setAccessible(true);
            Object o = null;
            try {
                o = field.get(saleExcel);
                if(o instanceof String) {
                    String str = (String) o;
                    if(ZhTwConverterUtil.containsTraditional(str)) {
                        str = ZhTwConverterUtil.toSimple(str);
                    }
                    field.set(saleExcel, str);
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
//        System.out.println(saleExcel);
        return saleExcel;
    }

    private static final String IMPORT_SUCCESS = "导入成功";
    private static final String HASH_ALGORITHM = "SHA-256";

    public static <T> String encryptList(List<T> originalList) {
        StringBuilder stringBuilder = new StringBuilder();
        for (T item : originalList) {
            stringBuilder.append(item.toString());
        }

        try {
            MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
            byte[] hashedBytes = digest.digest(stringBuilder.toString().getBytes());

            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashedBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }

            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    public void coptcInsert() {
        synchronized (redisCache) {
            String str = (String) redisCache.getCacheObject("insertCoptc");
            System.out.println("==================");
            System.out.println(str);
            if("1".equals(str)) {
                throw new CustomException("500", "目前有销售订单正在插入,稍等");
            }
            redisCache.setCacheObject("insertCoptc", "1");
            String str2 = (String) redisCache.getCacheObject("insertCoptc");
            System.out.println("++++++++++++++");
            System.out.println(str2);

        }
    }


    @Transactional
    @Override
    public void getExcels(MultipartFile[] files, HttpServletResponse response) {
        // 校验文件类型
        for (MultipartFile file : files) {
            //判断是否是excel文件
            if (!isExcelFileByMime(file)) {
                throw new CustomException("500", "文件需要为Excel");
            }
        }
        // 异步处理每个文件
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (MultipartFile file : files) {
            CompletableFuture<Void> future = processExcelFileAsync(file,response);
            futures.add(future);
        }
        // 等待所有任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        redisCache.setCacheObject("insertCoptc", "0");
    }

    //异步处理
    @Async
    public CompletableFuture<Void> processExcelFileAsync(MultipartFile file,HttpServletResponse response) {
        try {
            synchronized (this) {
                List<SaleExcel> saleExcelList = new ArrayList<>();
                List<SaleExcel> originalExcelList = new ArrayList<>();
                InputStream inputStream = file.getInputStream();
                EasyExcel.read(inputStream       //需要输入的数据
                        , SaleExcel.class        //创建一个格式对应的类
                        , new PageReadListener<SaleExcel>(
                                dataList -> {
                                    for (SaleExcel saleExcel : dataList) {
                                        SaleExcel cp = new SaleExcel();
                                        BeanUtils.copyPropertiesIgnoreCase(saleExcel, cp);
                                        originalExcelList.add(cp);
                                        saleExcelList.add(convertToSimplifiedChinese(saleExcel));
                                    }
                                })).sheet().doRead();

                // 设置行号
                for (int i = 0; i < saleExcelList.size(); i++) {
                    saleExcelList.get(i).setRows(i + 2);
                    originalExcelList.get(i).setRows(i + 2);
                }

                // 预检查和数据加密
                preCheckExcel(saleExcelList);

                String encryptedListString = encryptList(saleExcelList);
                System.out.println("加密之后的值 = " + encryptedListString);
                Object cacheObject = redisCache.getCacheObject("excelUploadKey::" + encryptedListString);
                if (cacheObject != null) {
                    throw new CustomException("500", "24小时内已有完全一样的表格数据上传过");
                }

                // 检查Excel数据
                checkExcel(saleExcelList);

                for (int i = 0; i < saleExcelList.size(); i++) {
                    originalExcelList.get(i).setImportStatus(saleExcelList.get(i).getImportStatus());
                }

                List<SaleExcel> failedExcelList = new ArrayList<>();
                for (int i = 0; i < saleExcelList.size(); i++) {
                    if (!IMPORT_SUCCESS.equals(originalExcelList.get(i).getImportStatus())) {
                        failedExcelList.add(saleExcelList.get(i));
                    }
                }

                // 输出Excel文件
                try (OutputStream outputStream = new FileOutputStream("output.xlsx")) {
                    outputExcel(failedExcelList, saleExcelList, response);
                }

            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return CompletableFuture.completedFuture(null);
    }

    @Override
    public List<Attach> fileList(FileListDto fileListDto) {
        String keyValues = new String(fileListDto.getType() + "||" + fileListDto.getId());

        LambdaQueryWrapper<Attach> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Attach::getParent, fileListDto.getProgramId())
                .eq(Attach::getKeyvalues, keyValues)
                .eq(Attach::getCompanyid, fileListDto.getCompanyId());
        return attachMapper.selectList(wrapper);
    }

    private void preCheckExcel(List<SaleExcel> saleExcelList) {
        for(SaleExcel saleExcel : saleExcelList) {
            if(StringUtils.isNotEmpty(saleExcel.getImportStatus())) {
                throw new CustomException("500", "新上传的文件中,[导入状态]不能有值");
            }
        }
    }

    /**
     * 导出Excel
     * @param saleExcelList
     */
    private void outputExcel(List<SaleExcel> originalExcelList, List<SaleExcel> saleExcelList,
                             HttpServletResponse response) throws IOException {
//        try {
//            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//            response.setCharacterEncoding("utf-8");
//            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
//            String fileName = "";
//            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
//            // 这里需要设置不关闭流
//            EasyExcel.write(response.getOutputStream(), SaleExcel.class)
//                    .autoCloseStream(Boolean.FALSE)
//                    .sheet("原数据")
//                    .doWrite(originalExcelList);
//        } catch (Exception e) {
//            // 重置response
//            response.reset();
//            response.setContentType("application/json");
//            response.setCharacterEncoding("utf-8");
//            Map<String, String> map = new HashMap<>();
//            map.put("status", "failure");
//            map.put("message", "下载文件失败" + e.getMessage());
//            response.getWriter().println(JSON.toJSONString(map));
//        }

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + "response" + ".xlsx");

        Set<Integer> set = new HashSet<>();
        for(SaleExcel saleExcel : saleExcelList) {
            if(IMPORT_SUCCESS.equals(saleExcel.getImportStatus())) {
                continue;
            }
            set.add(saleExcel.getRows() - 1);
        }
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

        String fullNowTime = TimeUtils.getFullNowTime().replace(":", "-");
        // 追加新数据到第1个Sheet
        WriteSheet newSheet = EasyExcel.writerSheet(0, "导出结果" + fullNowTime).registerWriteHandler(new MyRowWriteHandler(set))
                .head(SaleExcel.class).build();
//        // 设置特定行的颜色样式
//        List<Integer> coloredRows = List.of(2, 4, 6); // 假设要设置第3、5、7行的颜色
//        HorizontalCellStyleStrategy horizontalCellStyleStrategy = getCellStyleStrategy(coloredRows);
//
//        // 将样式策略应用到导出结果Sheet
//        newSheet.setC(horizontalCellStyleStrategy);

        excelWriter.write(saleExcelList, newSheet);

        // 写入原有数据到第2个Sheet
        WriteSheet originalSheet = EasyExcel.writerSheet(1, "错误列表")
                .head(SaleExcel.class).build();
        excelWriter.write(originalExcelList, originalSheet);

        excelWriter.finish();

        response.getOutputStream().close();

//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentDispositionFormData("attachment", "example.xlsx");


    }

    /**
     * 判断Excel中的銷售去向 传值是否正确
     * @param salesDestination
     * @return
     */
    private Boolean salesDestinationIsTrue(String salesDestination) {
        if(StringUtils.isEmpty(salesDestination)) return false;
        // 内销 外销 备货 样品
        if(salesDestination.equals("内销")) return true;
        if(salesDestination.equals("外销")) return true;
        if(salesDestination.equals("备货")) return true;
        if(salesDestination.equals("样品")) return true;
        return false;
    }

    public static boolean isInteger(String str) {
        if(StringUtils.isEmpty(str)) return false;
        // 使用正则表达式判断字符串是否为纯正整数
        return str.matches("^[1-9]\\d*$");
    }

    /**
     * 判断字符串是否为正数
     * @param str
     * @return
     */
    public static boolean isNumber(String str) {
        if(StringUtils.isEmpty(str)) return false;
        // 使用正则表达式判断字符串是否为数字类型
        return str.matches("^[0-9]+(\\.[0-9]+)?$");
    }

    private void checkExcel(List<SaleExcel> saleExcelList) {
        // key为，客戶訂單^^客戶
        Map<String, List<SaleExcel>> map = new HashMap<>();
        // 最终能插入的map分组
        Map<String, List<SaleExcel>> insertMap = new HashMap<>();

        // 把能进行分组操作的先分组, 没有客户订单和客户编号的不能进行分组。直接错误
        for(SaleExcel saleExcel : saleExcelList) {
            Boolean flag = true;
            StringBuffer result = new StringBuffer();

            if(StringUtils.isEmpty(saleExcel.getCustomOrder())) {
                result.append("错误：客户订单不能为空。\n");
                flag = false;
            }

            String customId = "";
            if(StringUtils.isEmpty(saleExcel.getCustomId())) {
                result.append("错误：客户不能为空。\n");
                flag = false;
            }else{
                Integer i = copmaMapper.selectCount(new LambdaQueryWrapper<Copma>().eq(Copma::getMa001, saleExcel.getCustomId()));
                if(i == 1) {
                    customId = saleExcel.getCustomId();
                }
                if(i == null || i == 0) {
                    Integer count = copmaMapper.selectCount(new LambdaQueryWrapper<Copma>().eq(Copma::getMa002, saleExcel.getCustomId()));
                    if(count == 1) {
                        Copma copma = copmaMapper.selectOne(new LambdaQueryWrapper<Copma>().eq(Copma::getMa002, saleExcel.getCustomId()));
                        customId = copma.getMa001();
                    }else{
                        Integer count2 = copmaMapper.selectCount(new LambdaQueryWrapper<Copma>().eq(Copma::getMa003, saleExcel.getCustomId()));
                        if(count2 == 1) {
                            Copma copma = copmaMapper.selectOne(new LambdaQueryWrapper<Copma>().eq(Copma::getMa003, saleExcel.getCustomId()));
                            customId = copma.getMa001();
                        }else{
                            result.append("错误：客户不存在。请输入客户编号,客户简称或者客户全称。\n");
                            flag = false;
                        }
                    }
                }
            }
            if(flag == false) {
                saleExcel.setImportStatus(result.toString());
                continue;
            }
            saleExcel.setCustomId(customId);

            // 第一次检查没问题的话, 将行分组   (客户订单，客户ID)
            String key = saleExcel.getCustomOrder() + "^^" + customId;
            List<SaleExcel> list = map.get(key);
            if(list == null) {
                list = new ArrayList<>();
            }
            list.add(saleExcel);
            map.put(key, list);
        }

        // 对同组的单子, 进行第二次筛选 (判断日期格式是否正确 以及 商品信息和销售去向是否正确  客户订单日期不能为空, 分组中单头信息是否一致)
        for (Map.Entry<String, List<SaleExcel>> entry : map.entrySet()) {

//            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
            List<SaleExcel> excelList = entry.getValue();
            Boolean finalFlag = true;
            Boolean flag = true;
            StringBuffer result = new StringBuffer();
            // 1. 对同组的每条, 进行格式筛选
            for(SaleExcel saleExcel : excelList) {
                if(!salesDestinationIsTrue(saleExcel.getSalesDestination())) {
                    result.append("第" + saleExcel.getRows() + "行错误：[销售去向]不能为空, 或者值需要为内销，外销，备货，样品中的一个。\n");
                    flag = false;
                }
                if(StringUtils.isEmpty(saleExcel.getCustomOrderDate())) {
                    result.append("第" + saleExcel.getRows() + "行错误：[客户订单日期]不能为空。\n");
                    flag = false;
                }else{
                    if(TimeUtils.isValidDate(saleExcel.getCustomOrderDate()) == false) {
                        result.append("第" + saleExcel.getRows() + "行错误：[客户订单日期]格式需要为年/月/日。\n");
                        flag = false;
                    }
                }
                // 订单日期
                if(StringUtils.isNotEmpty(saleExcel.getOrderDate()) && !TimeUtils.isValidDate(saleExcel.getOrderDate())) {
                    result.append("第" + saleExcel.getRows() + "行错误：[订单日期]格式需要为年/月/日。\n");
                    flag = false;
                }
                // 預定交貨日
                if(StringUtils.isNotEmpty(saleExcel.getScheduledDeliveryDate()) && !TimeUtils.isValidDate(saleExcel.getScheduledDeliveryDate())) {
                    result.append("第" + saleExcel.getRows() + "行错误：[预定交货日]格式需要为年/月/日。\n");
                    flag = false;
                }
                // 生管確認日
                if(StringUtils.isNotEmpty(saleExcel.getProductionManagementConfirmationDate()) && !TimeUtils.isValidDate(saleExcel.getProductionManagementConfirmationDate())) {
                    result.append("第" + saleExcel.getRows() + "行错误：[生管确认日]格式需要为年/月/日。\n");
                    flag = false;
                }

                // 判断商品存不存在
                if(StringUtils.isEmpty(saleExcel.getCommodity())) {
                    result.append("第" + saleExcel.getRows() + "行错误：[商品]不能为空。\n");
                    flag = false;
                }else{
                    Integer count = invmbMapper.selectCount(new LambdaQueryWrapper<Invmb>().eq(Invmb::getMb001, saleExcel.getCommodity()));
                    if(count != 1) {
                        result.append("第" + saleExcel.getRows() + "行错误：[商品]不存在。请输入商品编号。\n");
                        flag = false;
                    }
                }
                if(StringUtils.isEmpty(saleExcel.getAmount())) {
                    result.append("第" + saleExcel.getRows() + "行错误：[数量]不能为空。\n");
                    flag = false;
                }
                if(!isNumber(saleExcel.getAmount())) {
                    result.append("第" + saleExcel.getRows() + "行错误：[数量]需要为正数。\n");
                    flag = false;
                }
                if(flag == false) finalFlag = false;
            }
            // 2. 判断同组的单头信息 是否一致
            Boolean isSame = true;
            StringBuffer sameResult = new StringBuffer();
            SaleExcel saleExcel0 = excelList.get(0);
            for (int i = 1; i < excelList.size(); i++) {
                SaleExcel saleExcelI = excelList.get(i);
                // 订单日期
                if(!isSameContent(saleExcelI.getOrderDate(), saleExcel0.getOrderDate())) {
                    isSame = false;
                    sameResult.append("[订单日期]同组中需要一致。\n");
                }
                // 客户订单日期
                if(!isSameContent(saleExcelI.getCustomOrderDate(), saleExcel0.getCustomOrderDate())) {
                    isSame = false;
                    sameResult.append("[客户订单日期]同组中需要一致。\n");
                }
                // 币别
                if(!isSameContent(saleExcelI.getCoinType(), saleExcel0.getCoinType())) {
                    isSame = false;
                    sameResult.append("[币别]同组中需要一致。\n");
                }
                // 订单汇率
                if(!isSameContent(saleExcelI.getOrderExchangeRate(), saleExcel0.getOrderExchangeRate())) {
                    isSame = false;
                    sameResult.append("[订单汇率]同组中需要一致。\n");
                }
                // 税别
                if(!isSameContent(saleExcelI.getTaxType(), saleExcel0.getTaxType())) {
                    isSame = false;
                    sameResult.append("[税别]同组中需要一致。\n");
                }
                // 单价含税
                if(!isSameContent(saleExcelI.getUnitPriceIncludesTax(), saleExcel0.getUnitPriceIncludesTax())) {
                    isSame = false;
                    sameResult.append("[单价含税]同组中需要一致。\n");
                }
                // 业务员
                if(!isSameContent(saleExcelI.getSalesMan(), saleExcel0.getSalesMan())) {
                    isSame = false;
                    sameResult.append("[业务员]同组中需要一致。\n");
                }
                // 销售部门
                if(!isSameContent(saleExcelI.getSalesDepartment(), saleExcel0.getSalesDepartment())) {
                    isSame = false;
                    sameResult.append("[销售部门]同组中需要一致。\n");
                }
                // 付款条件
                if(!isSameContent(saleExcelI.getPaymentTerms(), saleExcel0.getPaymentTerms())) {
                    isSame = false;
                    sameResult.append("[付款条件]同组中需要一致。\n");
                }
                // 送货地址
                if(!isSameContent(saleExcelI.getShippingAddress(), saleExcel0.getShippingAddress())) {
                    isSame = false;
                    sameResult.append("[送货地址]同组中需要一致。\n");
                }
                // 发票地址
                if(!isSameContent(saleExcelI.getInvoiceAddress(), saleExcel0.getInvoiceAddress())) {
                    isSame = false;
                    sameResult.append("[发票地址]同组中需要一致。\n");
                }
                // 发票类型
                if(!isSameContent(saleExcelI.getInvoiceType(), saleExcel0.getInvoiceType())) {
                    isSame = false;
                    sameResult.append("[发票类型]同组中需要一致。\n");
                }
                // 交易条件
                if(!isSameContent(saleExcelI.getTransactionTerms(), saleExcel0.getTransactionTerms())) {
                    isSame = false;
                    sameResult.append("[交易条件]同组中需要一致。\n");
                }
                // 专案名称
                if(!isSameContent(saleExcelI.getProjectName(), saleExcel0.getProjectName())) {
                    isSame = false;
                    sameResult.append("[专案名称]同组中需要一致。\n");
                }
                // 唛头
                if(!isSameContent(saleExcelI.getMark(), saleExcel0.getMark())) {
                    isSame = false;
                    sameResult.append("[唛头]同组中需要一致。\n");
                }
                // 供应链订单
                if(!isSameContent(saleExcelI.getSupplyChainOrder(), saleExcel0.getSupplyChainOrder())) {
                    isSame = false;
                    sameResult.append("[供应链订单]同组中需要一致。\n");
                }
                // 分次开票
                if(!isSameContent(saleExcelI.getInvoicingInInstallments(), saleExcel0.getInvoicingInInstallments())) {
                    isSame = false;
                    sameResult.append("[分次开票]同组中需要一致。\n");
                }
                // 备注
//                if(!isSameContent(saleExcelI.getHeadRemark(), saleExcel0.getHeadRemark())) {
//                    isSame = false;
//                    sameResult.append("[合并]。\n");
//                }
                // 销售去向
                if(!isSameContent(saleExcelI.getSalesDestination(), saleExcel0.getSalesDestination())) {
                    isSame = false;
                    sameResult.append("[销售去向]同组中需要一致。\n");
                }
            }
            if(finalFlag == false) {
                result.insert(0, "在客户订单和客户编号相同的分组中,有以下行有错误。\n");
                for(SaleExcel saleExcel : excelList) {
                    saleExcel.setImportStatus(result.toString() + "\n");
                }
            }
            if(isSame == false) {
                sameResult.insert(0, "在同组中, 单头信息有以下不一致。\n");
                for(SaleExcel saleExcel : excelList) {
                    if(StringUtils.isEmpty(saleExcel.getImportStatus())) saleExcel.setImportStatus(sameResult.toString());
                    else saleExcel.setImportStatus(saleExcel.getImportStatus() + sameResult.toString());
                }
            }
            if(finalFlag == false || isSame == false) {
                continue;
            }
            insertMap.put(entry.getKey(), entry.getValue());
        }
        Map<String, List<SaleExcel>> finalMap = new HashMap<>();
        // 对能最后插入的分组, 进行值的判断和插入
        for(Map.Entry<String, List<SaleExcel>> entry : insertMap.entrySet()) {
            Boolean flag = true;
            StringBuffer sb = new StringBuffer();
            for(SaleExcel saleExcel : entry.getValue()) {
                // 先对对象中的属性 进行赋值 (赋值成可以直接插入TABLE的形式)
                // 销售订单 单别 单号      内销，外销，备货，样品
                String TC001 = "", TC002 = "";
                switch (saleExcel.getSalesDestination()) {
                    case "内销":
                        TC001 = cmsmqService.getOne(new LambdaQueryWrapper<Cmsmq>().eq(Cmsmq::getMq003, "22").like(Cmsmq::getMq002, "內销")).getMq001();
                        break;
                    case "外销":
                        TC001 = cmsmqService.getOne(new LambdaQueryWrapper<Cmsmq>().eq(Cmsmq::getMq003, "22").like(Cmsmq::getMq002, "外销")).getMq001();
                        break;
                    case "备货":
                        TC001 = cmsmqService.getOne(new LambdaQueryWrapper<Cmsmq>().eq(Cmsmq::getMq003, "22").like(Cmsmq::getMq002, "备")).getMq001();
                        break;
                    case "样品":
                        TC001 = cmsmqService.getOne(new LambdaQueryWrapper<Cmsmq>().eq(Cmsmq::getMq003, "22").like(Cmsmq::getMq002, "样品")).getMq001();
                        break;
                }
                saleExcel.setSaleOrderId(TC001);
//                TC002 = coptcMapper.selectTc002(TC001);
                // 订单日期
                if(StringUtils.isEmpty(saleExcel.getOrderDate())) {
                    saleExcel.setOrderDate(TimeUtils.HZStdTime());
                }else{
                    saleExcel.setOrderDate(TimeUtils.stringToHZStdTime(saleExcel.getOrderDate()));
                }
                // 把客户订单日期转成HZ日期格式 如果有数据的话
                if(StringUtils.isNotEmpty(saleExcel.getCustomOrderDate())) {
                    saleExcel.setCustomOrderDate(TimeUtils.stringToHZStdTime(saleExcel.getCustomOrderDate()));
                }
                // 供应商信息
                Copma copma = copmaMapper.selectOne(new LambdaQueryWrapper<Copma>().eq(Copma::getMa001, saleExcel.getCustomId()));
                // 查询币别
                Cmsmf cmsmf = cmsmfMapper.selectOne(new LambdaQueryWrapper<Cmsmf>().eq(Cmsmf::getMf001, saleExcel.getCoinType())
                        .or().eq(Cmsmf::getMf002, saleExcel.getCoinType()));
                if(cmsmf == null) {
                    saleExcel.setCoinType(copma.getMa014());
                }else{
                    saleExcel.setCoinType(cmsmf.getMf001());
                }
                // 订单汇率
                if("RMB".equals(saleExcel.getCoinType()) || saleExcel.getCoinType() == null) {
                    saleExcel.setOrderExchangeRate("1");
                }else{
                    Result result = cmsmgController.latestExchangeRate(saleExcel.getCoinType());
                    System.out.println(result);
                    saleExcel.setOrderExchangeRate(((Double) result.getData()).toString());
                }
                // 税别
                if(StringUtils.isEmpty(saleExcel.getTaxType())) {
                    saleExcel.setTaxType(copma.getMa038());
                }else{
                    if(isInteger(saleExcel.getTaxType())) {
                        switch (saleExcel.getTaxType()) {
                            case "1":
                                break;
                            case "2":
                                break;
                            case "3":
                                break;
                            case "4":
                                break;
                            case "9":
                                break;
                            default:
                                saleExcel.setTaxType(copma.getMa038());
                                break;
                        }
                    }else{
                        switch (saleExcel.getTaxType()) {
                            case "应税内含":
                                saleExcel.setTaxType("1");
                                break;
                            case "应税外加":
                                saleExcel.setTaxType("2");
                                break;
                            case "零税率":
                                saleExcel.setTaxType("3");
                                break;
                            case "免税":
                                saleExcel.setTaxType("4");
                                break;
                            case "不计税":
                                saleExcel.setTaxType("9");
                                break;
                            default:
                                saleExcel.setTaxType(copma.getMa038());
                                break;
                        }
                    }
                }

                // 單價含稅 (存扩展字段)
                if(StringUtils.isEmpty(saleExcel.getUnitPriceIncludesTax())
                        || (!saleExcel.getUnitPriceIncludesTax().equals("1") && !saleExcel.getUnitPriceIncludesTax().equals("0"))) {
                    if(saleExcel.getTaxType().equals("1")) saleExcel.setUnitPriceIncludesTax("1");
                    else saleExcel.setUnitPriceIncludesTax("0");
                }else{
                    if(saleExcel.getTaxType().equals("1")) {
                        if(saleExcel.getUnitPriceIncludesTax().equals("0")) {
                            flag = false;
                            sb.append("错误：[单价含税]为不含税时, 不能选择[税别]为应税内含。\n");
                        }
                    }else{
                        if(saleExcel.getUnitPriceIncludesTax().equals("1")) {
                            flag = false;
                            sb.append("错误：[单价含税]为含税时, 需要选择[税别]为应税内含。\n");
                        }
                    }
                }
                // 业务员
                Integer count = cmsmvMapper.selectCount(new LambdaQueryWrapper<Cmsmv>().eq(Cmsmv::getMv001, saleExcel.getSalesMan())
                        .or().eq(Cmsmv::getMv002, saleExcel.getSalesMan()));
                if(count == null || count != 1) saleExcel.setSalesMan(copma.getMa016());
                else {
                    saleExcel.setSalesMan(cmsmvMapper.selectOne(new LambdaQueryWrapper<Cmsmv>().eq(Cmsmv::getMv001, saleExcel.getSalesMan())
                            .or().eq(Cmsmv::getMv002, saleExcel.getSalesMan())).getMv001());
                }
                // 销售部门
                Integer count1 = cmsmeMapper.selectCount(new LambdaQueryWrapper<Cmsme>().eq(Cmsme::getMe001, saleExcel.getSalesDepartment())
                        .or().eq(Cmsme::getMe002, saleExcel.getSalesDepartment()).or().eq(Cmsme::getMe003, saleExcel.getSalesDepartment()));
                if(count1 == null || count1 != 1) saleExcel.setSalesDepartment(copma.getMa015());
                else {
                    saleExcel.setSalesDepartment(cmsmeMapper.selectOne(new LambdaQueryWrapper<Cmsme>()
                            .eq(Cmsme::getMe001, saleExcel.getSalesDepartment())
                            .or().eq(Cmsme::getMe002, saleExcel.getSalesDepartment())
                            .or().eq(Cmsme::getMe003, saleExcel.getSalesDepartment())).getMe001());
                }
                // 付款条件
                if(StringUtils.isEmpty(saleExcel.getPaymentTerms())) {
                    saleExcel.setPaymentTerms(copma.getMa083());
                }else{
                    List<Cmsna> cmsnas = cmsnaMapper.selectBusiness(saleExcel.getPaymentTerms());
                    if(cmsnas != null && cmsnas.size() == 1) saleExcel.setPaymentTerms(cmsnas.get(0).getNa002());
                    else {
                        saleExcel.setPaymentTerms(copma.getMa083());
                    }
                }
                // 送货地址 如果为空
                if(StringUtils.isEmpty(saleExcel.getShippingAddress())) {
                    if(StringUtils.isNotEmpty(copma.getMa027())) {
                        saleExcel.setShippingAddress(copma.getMa027());
                    }else{
                        Coptc latestCoptcByCustomId = coptcMapper.getLatestCoptcByCustomId(saleExcel.getCustomId());
                        if(latestCoptcByCustomId != null && StringUtils.isNotEmpty(latestCoptcByCustomId.getTc010())) {
                            saleExcel.setShippingAddress(latestCoptcByCustomId.getTc010());
                        }
                    }
                }
                // 發票地址
                if(StringUtils.isEmpty(saleExcel.getInvoiceAddress())) {
                    if(StringUtils.isNotEmpty(copma.getMa025())) {
                        saleExcel.setInvoiceAddress(copma.getMa025());
                    }else{
                        Coptc latestCoptcByCustomId = coptcMapper.getLatestCoptcByCustomId(saleExcel.getCustomId());
                        if(latestCoptcByCustomId != null && StringUtils.isNotEmpty(latestCoptcByCustomId.getUdf08())) {
                            saleExcel.setInvoiceAddress(latestCoptcByCustomId.getUdf08());
                        }
                    }
                }
                // 发票类型  A.专用发票、B.普通发票、C.其他
                if(StringUtils.isNotEmpty(saleExcel.getInvoiceType())) {
                    switch (saleExcel.getInvoiceType()) {
                        case "A":
                            break;
                        case "B":
                            break;
                        case "C":
                            break;
                        case "专用发票":
                            saleExcel.setTaxType("A");
                            break;
                        case "普通发票":
                            saleExcel.setTaxType("B");
                            break;
                        case "其他":
                            saleExcel.setTaxType("C");
                            break;
                        default:
                            saleExcel.setInvoiceType(copma.getMa037());
                            break;
                    }
                }else{
                    saleExcel.setInvoiceType(copma.getMa037());
                }
                // 交易條件
                if(StringUtils.isEmpty(saleExcel.getTransactionTerms())) {
                    Coptc latestCoptcByCustomId = coptcMapper.getLatestCoptcByCustomId(saleExcel.getCustomId());
                    if(latestCoptcByCustomId != null) saleExcel.setTransactionTerms(latestCoptcByCustomId.getUdf02());
                }
                // 專案名稱
                // 嘜頭
                // 供應鏈訂單
                if(StringUtils.isEmpty(saleExcel.getSupplyChainOrder())
                        || (!saleExcel.getSupplyChainOrder().equals("0") && !saleExcel.getSupplyChainOrder().equals("1"))) {
                    saleExcel.setSupplyChainOrder("0");
                }
                // 分次開票
                // 备注


                // 单身判断 先拿出要用的值
                Invmb invmb = invmbMapper.selectOne(new LambdaQueryWrapper<Invmb>().eq(Invmb::getMb001, saleExcel.getCommodity()));
                // 单位
                if(StringUtils.isEmpty(saleExcel.getUnit())) {
                    saleExcel.setUnit(invmb.getMb004());
                }
                // 单价
                if(StringUtils.isEmpty(saleExcel.getUnitPrice()) || !isNumber(saleExcel.getUnitPrice())) {
                    Double price = coptbMapper.getPriceByCustomId(saleExcel.getCustomId(), saleExcel.getCommodity(), TimeUtils.HZStdTime());
                    if(price != null) {
                        saleExcel.setUnitPrice(price.toString());
                    }else{
//                        Double latestPrice = coptdMapper.getLatestPrice(saleExcel.getCommodity(), saleExcel.getCustomId());
//                        if(latestPrice != null) {
//                            saleExcel.setUnitPrice(latestPrice.toString());
//                        }else{
//                            flag = false;
                        sb.append("错误：[单价]在核价单中没有符合的数据, 需要在Excel中传入数字类型的值。\n");
//                        }
                    }
                }
                // 预定交货日
                if(StringUtils.isNotEmpty(saleExcel.getScheduledDeliveryDate())) {
                    String date = TimeUtils.stringToHZStdTime(saleExcel.getScheduledDeliveryDate());
                    if(date.toString().compareTo(saleExcel.getOrderDate()) < 0) {
                        saleExcel.setScheduledDeliveryDate(saleExcel.getOrderDate());
                    } else saleExcel.setScheduledDeliveryDate(date);
                }
                // 运送方式   1.空运、2.海运、3.海空联运、4.邮寄、5.陆运、6.自取、7.自送、8.快递
                if(StringUtils.isEmpty(saleExcel.getShippingMethod())) {
                    saleExcel.setShippingMethod(copma.getMa048());
                }else{
                    if(isInteger(saleExcel.getShippingMethod())) {
                        if(Integer.parseInt(saleExcel.getShippingMethod()) > 8
                                || Integer.parseInt(saleExcel.getShippingMethod()) < 1) {
                            saleExcel.setShippingMethod(copma.getMa048());
                        }
                    }else{
                        switch (saleExcel.getShippingMethod()) {
                            case "空运":
                                saleExcel.setShippingMethod("1");
                                break;
                            case "海运":
                                saleExcel.setShippingMethod("2");
                                break;
                            case "海空联运":
                                saleExcel.setShippingMethod("3");
                                break;
                            case "邮寄":
                                saleExcel.setShippingMethod("4");
                                break;
                            case "陆运":
                                saleExcel.setShippingMethod("5");
                                break;
                            case "自取":
                                saleExcel.setShippingMethod("6");
                                break;
                            case "自送":
                                saleExcel.setShippingMethod("7");
                                break;
                            case "快递":
                                saleExcel.setShippingMethod("8");
                                break;
                            default:
                                saleExcel.setShippingMethod(copma.getMa048());
                                break;
                        }
                    }
                }

                // 仓库
                Integer count3 = cmsmcMapper.selectCount(new LambdaQueryWrapper<Cmsmc>().eq(Cmsmc::getMc001, saleExcel.getStorehouse())
                        .or().eq(Cmsmc::getMc002, saleExcel.getStorehouse()));
                if(count3 == null || count3 != 1) {
                    saleExcel.setStorehouse(invmb.getMb017());
                }else{
                    saleExcel.setStorehouse(cmsmcMapper.selectOne(new LambdaQueryWrapper<Cmsmc>().eq(Cmsmc::getMc001, saleExcel.getStorehouse())
                            .or().eq(Cmsmc::getMc002, saleExcel.getStorehouse())).getMc001());
                }
                // 销售/代工
                if(StringUtils.isEmpty(saleExcel.getSalesOEM())
                        || (!saleExcel.getSalesOEM().equals("0") && !saleExcel.getSalesOEM().equals("1"))) {
                    saleExcel.setSalesOEM("0");
                }
                // 生管确认日  不需要把斜杠去掉
                if(StringUtils.isNotEmpty(saleExcel.getProductionManagementConfirmationDate())) {
                    saleExcel.setProductionManagementConfirmationDate
                            (TimeUtils.stringToHZStdTime(saleExcel.getProductionManagementConfirmationDate()));
                }
                // 備品
                if(StringUtils.isEmpty(saleExcel.getSpareParts())
                        || (!saleExcel.getSpareParts().equals("0") && !saleExcel.getSpareParts().equals("1"))) {
                    saleExcel.setSpareParts("0");
                }
                // 保稅  如果是内销, 只能是非保税
                if(StringUtils.isNotEmpty(saleExcel.getBonded()) && saleExcel.getBonded().equals("1")
                        && TC001.equals("ASOC")) {
                    saleExcel.setBonded("0");
                }else if(StringUtils.isEmpty(saleExcel.getBonded())
                        || (!saleExcel.getBonded().equals("0") && !saleExcel.getBonded().equals("1"))) {
                    saleExcel.setBonded("0");
                }

            }
            // 有错误, 同组都不能添加
            if(flag == false) {
                for(SaleExcel saleExcel : entry.getValue()) {
                    saleExcel.setImportStatus(sb.toString());
                }
                continue;
            }
            finalMap.put(entry.getKey(), entry.getValue());
        }
        List<List<SaleExcel>> finalList = new ArrayList<>();
        // 排序
        for(SaleExcel saleExcel : saleExcelList) {
            if(saleExcel.getImportStatus() == null || "".equals(saleExcel.getImportStatus().trim())) {
                if(finalMap.get(saleExcel.getCustomOrder() + "^^" + saleExcel.getCustomId()) == null) continue;
                finalList.add(finalMap.remove(saleExcel.getCustomOrder() + "^^" + saleExcel.getCustomId()));
            }
        }
        if(finalMap.size() > 0) {
            throw new CustomException("500", "集合排序错误");
        }

//        List<List<SaleExcel>> lists = mergeAndGroupSaleExcelList(finalList,2);
        MyUser myUser = SecurityUtils.getLoginUser();
        if(myUser == null) {
            throw new CustomException("500","用户没有登录,请登录");
        }
        for(List<SaleExcel> value : finalList) {
            // 检查没有问题的, 进行插入操作
            SaleExcel saleExcel = value.get(0);
            Coptc coptc = new Coptc();
            coptc.setCompany(YmlConfig.getYFCOMPANY());
            coptc.setCreator(myUser.getUsername());
            log.info(myUser.getName()+"测试名称");
            coptc.setUdf11(myUser.getName());
            coptc.setCreateDate(TimeUtils.getNowTime());
            coptc.setFlag(new Double(1));

            coptc.setTc001(saleExcel.getSaleOrderId());
//            cmsmqService.getIdByType(saleExcel.getSaleOrderId(), "COPTC");
            coptc.setTc002(cmsmqService.getIdByType(coptc.getTc001(), "coptc"));
//            coptc.setTc002(coptcMapper.selectTc002(saleExcel.getSaleOrderId()));
//            saleExcel.setSaleOrderId(coptc.getTc001() + "-" + coptc.getTc002());
            coptc.setTc003(saleExcel.getOrderDate()); // 订单日期
            coptc.setTc004(saleExcel.getCustomId()); // 客户编号
            coptc.setTc005(saleExcel.getSalesDepartment()); // 部门编号
            coptc.setTc006(saleExcel.getSalesMan()); // 业务人员
            coptc.setTc007("01"); // 出货工厂
            coptc.setTc008(saleExcel.getCoinType());  // 交易币种
            coptc.setTc009(Double.parseDouble(saleExcel.getOrderExchangeRate())); // 订单汇率
            coptc.setTc010(saleExcel.getShippingAddress()); // 送货地址一
            coptc.setTc011(""); // 送货地址二
            coptc.setTc012(saleExcel.getCustomOrder()); // 客户单号
            coptc.setTc013(""); // 价格说明
            Cmsna cmsna = cmsnaMapper.selectOne(new LambdaQueryWrapper<Cmsna>().eq(Cmsna::getNa001, "2")
                    .eq(Cmsna::getNa002, saleExcel.getPaymentTerms()));
            coptc.setTc014(cmsna.getNa003()); // 付款条件名称
            coptc.setTc016(saleExcel.getTaxType());  // 税种
            coptc.setTc019(saleExcel.getShippingMethod()); // 運送方式
            coptc.setTc027("N"); // 审核码
            coptc.setTc032("");  // 收货人ID
            coptc.setTc039(saleExcel.getOrderDate()); // 单据日期
            coptc.setTc040(""); // 审核者
            // 供应商信息
            Copma copma = copmaMapper.selectOne(new LambdaQueryWrapper<Copma>().eq(Copma::getMa001, saleExcel.getCustomId()));
            if(saleExcel.getTaxType().equals("3")) coptc.setTc041(0D);  // 税率
            else coptc.setTc041(copma.getMa101());
            coptc.setTc042(saleExcel.getPaymentTerms());  // 付款条件编号
            coptc.setTc048("0");  // 签核状态码
            coptc.setTc050("N");  // 抛转状态
            coptc.setTc056(saleExcel.getMark());   // 正唛
            coptc.setTc077("********************");  // 项目编号
            coptc.setUdf01(saleExcel.getSupplyChainOrder());  // 供应链采购单号
            coptc.setUdf02(saleExcel.getTransactionTerms());  // 交易条件
            coptc.setUdf08(saleExcel.getInvoiceAddress());  // 發票地址
            coptc.setUdf09(saleExcel.getInvoiceType());  // 發票类型
            coptc.setUdf10(saleExcel.getProjectName());  // 專案名稱
//            coptc.setUdf11(saleExcel.getInvoicingInInstallments());  // 分次開票

            if (StringUtils.isNotEmpty(coptc.getUdf08()) && StringUtils.isNotEmpty(coptc.getTc004())) {
                Copma copma2 = copmaMapper.selectOne(new LambdaQueryWrapper<Copma>().eq(Copma::getMa001, coptc.getTc004()));
                if (copma2 != null) {
                    Integer count = copmdMapper.selectCount(new LambdaQueryWrapper<Copmd>().eq(Copmd::getMd001, coptc.getTc004())
                            .eq(Copmd::getMd003, coptc.getUdf08()));
                    if (count == null || count == 0) {
                        Copmd copmd = new Copmd();
                        copmd.setCompany(YmlConfig.getYFCOMPANY());
                        copmd.setCreator(myUser.getUsername());
                        copmd.setCreateDate(TimeUtils.getNowTime());
                        copmd.setFlag(0D);
                        copmd.setMd001(coptc.getTc004());
                        String md002 = copmdMapper.generateMd002(coptc.getTc004());
                        copmd.setMd002(md002);
                        copmd.setMd003(coptc.getUdf08());
                        copmd.setMd006(copma2.getMa003());
                        copmdMapper.insert(copmd);
                    }
                }
                Copma copma1 = this.copmaMapper.selectOne(new LambdaQueryWrapper<Copma>().eq(Copma::getMa001, coptc.getTc004()).eq(Copma::getMa025, coptc.getUdf08()));
                if (copma1==null){
                    copma2.setMa025(coptc.getUdf08());
                    this.copmaMapper.update(copma2,new LambdaQueryWrapper<Copma>().eq(Copma::getMa001, coptc.getTc004()));
                }
            }

            if (StringUtils.isNotEmpty(coptc.getTc010()) && StringUtils.isNotEmpty(coptc.getTc004())) {
                Integer count = copmdMapper.selectCount(new LambdaQueryWrapper<Copmd>().eq(Copmd::getMd001,coptc.getTc004()).eq(Copmd::getMd003, coptc.getTc010()));
                Copmd copmd = new Copmd();
                if (count == null || count == 0) {
                    copmd.setCompany(YmlConfig.getYFCOMPANY());
                    copmd.setCreator(myUser.getUsername());
                    copmd.setCreateDate(TimeUtils.getNowTime());
                    copmd.setFlag(0D);
                    copmd.setMd001(coptc.getTc004());
                    copmd.setMd005(coptc.getTc015());
                    copmd.setMd006(coptc.getUdf03());
                    copmd.setMd007(coptc.getUdf04());
                    copmd.setMd008(coptc.getTc073());
                    copmd.setMd009(coptc.getTc074());
                    copmd.setMd010(coptc.getTc075());
                    String md002 = copmdMapper.generateMd002(coptc.getTc004());
                    copmd.setMd002(md002);
                    copmd.setMd003(coptc.getTc010());
                    copmdMapper.insert(copmd);
                }
                Copma copma1 = this.copmaMapper.selectOne(new LambdaQueryWrapper<Copma>().eq(Copma::getMa001, coptc.getTc004()).eq(Copma::getMa027, coptc.getTc010()));
                if (copma1==null){
                    Copma copma2 = new Copma();
                    copma2.setMa027(coptc.getTc010());
                    this.copmaMapper.update(copma2,new LambdaQueryWrapper<Copma>().eq(Copma::getMa001, coptc.getTc004()));
                }
            }


            /**
             * COPTC.TCI01   客户合同交期
             * COPTC.TCI02   客户订单日期
             */
            coptc.setTci01(saleExcel.getCustomOrderDate());
            coptc.setTci02(saleExcel.getCustomOrderDate());
            BigDecimal tc029 = new BigDecimal(0D);  // 订单金额
            BigDecimal tc030 = new BigDecimal(0D);  // 订单税额
            BigDecimal tc031 = new BigDecimal(0D);  // 总数量
            BigDecimal tci03 = new BigDecimal(0D);  // 订单本币税前金额
            BigDecimal tci04 = new BigDecimal(0D);  // 订单本币税额
            BigDecimal udf51 = new BigDecimal(0D);  // 总和


            List<String> headRemarkList = new ArrayList<>();   // 用来按顺序存放不同的单头备注，之后合并到单头备注上
            // COPTD 插入
            int idx = 1;
            for(SaleExcel saleExcelItem : value) {

                // 判断备注是否一样，因为要排序。所以不用Set做
                boolean flag = true;
                for(String remark : headRemarkList) {
                    if(remark.trim().equals(saleExcelItem.getHeadRemark().trim())) {
                        flag = false;
                        break;
                    }
                }
                if(flag) {
                    headRemarkList.add(saleExcelItem.getHeadRemark());
                }

                RaxDto raxDto = new RaxDto();
                raxDto.setType(saleExcelItem.getTaxType());
                raxDto.setUnitPrice(new BigDecimal(saleExcelItem.getUnitPrice()));
                raxDto.setNums(new BigDecimal(saleExcelItem.getAmount()));
                raxDto.setRax(new BigDecimal(coptc.getTc041()));
                raxDto.setExchangeRate(new BigDecimal(saleExcelItem.getOrderExchangeRate()));
                RaxVo raxVo = MoneyUtils.getRax(raxDto);
//                System.out.println("金额"+raxVo);
                log.info("金额"+raxVo);
                Coptd coptd = new Coptd();
                coptd.setCompany(YmlConfig.getYFCOMPANY());
                coptd.setCreator(myUser.getUsername());
                coptd.setUdf11(myUser.getName());
                coptd.setCreateDate(TimeUtils.getNowTime());
                coptd.setFlag(new Double(1));

                coptd.setTd001(coptc.getTc001());
                coptd.setTd002(coptc.getTc002());
                saleExcelItem.setSaleOrderId(coptc.getTc001() + "-" + coptc.getTc002());
                coptd.setTd003(String.format("%04d", idx));
                saleExcelItem.setNO(String.format("%04d", idx));
                Invmb invmb = invmbMapper.selectOne(new LambdaQueryWrapper<Invmb>().eq(Invmb::getMb001, saleExcelItem.getCommodity()));
                coptd.setTd004(invmb.getMb001());  // 品号
                coptd.setTd005(invmb.getMb002());  // 品名
                coptd.setTd006(invmb.getMb003());  // 规格
                coptd.setTd007(saleExcelItem.getStorehouse());  // 仓库
                coptd.setTd008(Double.parseDouble(saleExcelItem.getAmount()));
                coptd.setTd010(saleExcelItem.getUnit());  // 单位
                coptd.setTd011(Double.parseDouble(saleExcelItem.getUnitPrice()));  // 单价
                coptd.setTd012(NumberUtil.round(raxVo.getPrice(), 6).doubleValue());  // 金额
                coptd.setUdf51(NumberUtil.round(raxVo.getPrice(), 6).doubleValue());  // 金额
                coptd.setTd013(saleExcelItem.getScheduledDeliveryDate()); // 預定交貨日
                // 客户品号
                if(StringUtils.isNotEmpty(saleExcelItem.getCustomerMerchandise())) {
                    Copmg copmg = copmgMapper.selectOne(new LambdaQueryWrapper<Copmg>().eq(Copmg::getMg001, saleExcelItem.getCustomId())
                            .eq(Copmg::getMg002, saleExcelItem.getCommodity()).eq(Copmg::getMg003, saleExcelItem.getCustomerMerchandise()));
                    if(copmg == null) {
                        Copmg newCopmg = new Copmg();
                        newCopmg.setCompany(YmlConfig.getYFCOMPANY());   newCopmg.setCreator("ERP");
                        newCopmg.setCreateDate(TimeUtils.getNowTime());   newCopmg.setFlag(1D);
                        newCopmg.setMg001(saleExcelItem.getCustomId());
                        newCopmg.setMg002(saleExcelItem.getCommodity());
                        newCopmg.setMg003(saleExcelItem.getCustomerMerchandise());
                        copmgMapper.insert(newCopmg);
                    }else {
                        coptd.setUdf04(copmg.getMg005());
                        coptd.setUdf05(copmg.getMg006());
                    }
                    coptd.setTd014(saleExcelItem.getCustomerMerchandise());
                }
                coptd.setTd016("N");  // 结束
                coptd.setTd020(saleExcelItem.getSingleNotes());  // 备注
                coptd.setTd021("N");  // 审核码
                coptd.setTd026(1D);  // 折扣率
                coptd.setTd027("********************");  // 项目编号

                coptd.setTd037(coptc.getTc041());  // 税率
                coptd.setTd038(NumberUtil.round(raxVo.getPriceBeforeTax(), 4).doubleValue());  // 税前金额
                coptd.setUdf52(NumberUtil.round(raxVo.getPriceBeforeTax(), 4).doubleValue()); // 自定义税前金额
                coptd.setTd039(NumberUtil.round(raxVo.getTaxPrice(), 4).doubleValue());  // 税额
                coptd.setUdf53(NumberUtil.round(raxVo.getTaxPrice(), 4).doubleValue()); // 自定义税额

                coptd.setTdi01(NumberUtil.round(raxVo.getPriceBeforeTaxLocal(), 6).doubleValue());  // 本币税前金额
                coptd.setUdf55(NumberUtil.round(raxVo.getPriceBeforeTaxLocal(), 6).doubleValue());

                coptd.setTdi02(NumberUtil.round(raxVo.getTaxPriceLocal(), 4).doubleValue());  // 本币税额
                coptd.setUdf56(NumberUtil.round(raxVo.getTaxPriceLocal(), 6).doubleValue());

                coptd.setTdi03(NumberUtil.round(raxVo.getPriceLocal(), 6).doubleValue());  // 本币金额
                coptd.setUdf54(NumberUtil.round(raxVo.getPriceLocal(), 6).doubleValue());

                /**
                 * UDF06保稅
                 * UDF07運送方式
                 * UDF08銷售/代工
                 * UDF09供應鏈流程
                 * UDF10備品
                 * UDF11使用保稅材料
                 * UDF12分廠
                 */
                if(saleExcelItem.getProductionManagementConfirmationDate()!=null){
                    coptd.setUdf03(saleExcelItem.getProductionManagementConfirmationDate());  // 生管确认日
                }else {
                    coptd.setUdf03(saleExcelItem.getScheduledDeliveryDate());  // 生管确认日为空时使用预交货日期
                }
                coptd.setUdf06(saleExcelItem.getBonded());
                coptd.setUdf07(saleExcelItem.getShippingMethod());
                coptd.setUdf08(saleExcelItem.getSalesOEM());
                coptd.setUdf09(saleExcelItem.getSupplyChainProcess());
                coptd.setUdf10(saleExcelItem.getSpareParts());
//                coptd.setUdf11(saleExcelItem.getUseBondedMaterials());
                coptd.setUdf12(saleExcelItem.getBranchFactory());

                tc029 = NumberUtil.add(tc029, raxVo.getPriceBeforeTax());  // 订单金额
                tc030 = NumberUtil.add(tc030, raxVo.getTaxPrice()); // 订单税额
                tc031 = NumberUtil.add(tc031, coptd.getTd008());  // 总数量
                tci03 = NumberUtil.add(tci03, raxVo.getPriceBeforeTaxLocal());  // 订单本币税前金额
                tci04 = NumberUtil.add(tci04, raxVo.getTaxPriceLocal());  // 订单本币税额
                udf51 = NumberUtil.add(udf51, raxVo.getPrice()); // 合计

                coptdMapper.insert(coptd);
                saleExcelItem.setImportStatus(IMPORT_SUCCESS);
                /**
                 * 注释一下特殊字段
                 */
                if(StringUtils.isNotEmpty(saleExcelItem.getStorehouse())) {
                    String mc002 = cmsmcMapper.selectOne(new LambdaQueryWrapper<Cmsmc>().eq(Cmsmc::getMc001, saleExcelItem.getStorehouse())).getMc002();
                    saleExcelItem.setStorehouse(saleExcelItem.getStorehouse().trim() + "(" + mc002.trim() + ")");
                }
                idx++;
            }
            coptc.setTc029(NumberUtil.round(udf51, 6).doubleValue());  // 订单金额
            coptc.setUdf51(NumberUtil.round(udf51, 6).doubleValue());  // 订单总金额
            coptc.setTc030(NumberUtil.round(tc030, 4).doubleValue());  // 订单税额
            coptc.setUdf52(NumberUtil.round(tc029, 6).doubleValue()); // 自定义税前金额
            coptc.setUdf53(NumberUtil.round(tc030, 4).doubleValue()); // 自定义税额
            coptc.setTc031(NumberUtil.round(tc031, 2).doubleValue());  // 总数量
            coptc.setTci03(NumberUtil.round(tci03, 4).doubleValue());  // 订单本币税前金额
            coptc.setTci04(NumberUtil.round(tci04, 4).doubleValue());  // 订单本币税额
            StringBuffer headRemark = new StringBuffer();
            for(String remark : headRemarkList) {
                headRemark.append(remark + "\n");
            }
            coptc.setREMARK(headRemark.toString());  // 备注
            // 把新整合好的备注，重新set到Excel中
            for(SaleExcel saleExcelItem : value) {
                saleExcelItem.setHeadRemark(headRemark.toString());
            }
            log.info(coptc+"值");
            coptcMapper.insert(coptc);
//            System.out.println(coptc.getTc001() + "  " + coptc.getTc002());
            for(SaleExcel saleExcelItem : value) {
                // 运输方式注释
                if(StringUtils.isNotEmpty(saleExcelItem.getShippingMethod())) {
                    String str = "";
                    switch (saleExcelItem.getShippingMethod()) {
                        case "1":
                            str = "空运";
                            break;
                        case "2":
                            str = "海运";
                            break;
                        case "3":
                            str = "海空联运";
                            break;
                        case "4":
                            str = "邮寄";
                            break;
                        case "5":
                            str = "陆运";
                            break;
                        case "6":
                            str = "自取";
                            break;
                        case "7":
                            str = "自送";
                            break;
                        case "8":
                            str = "快递";
                            break;
                    }
                    saleExcelItem.setShippingMethod(saleExcelItem.getShippingMethod() + "(" + str + ")");
                }
                // 税别
                if(StringUtils.isNotEmpty(saleExcelItem.getTaxType())) {
                    String str = "";
                    switch (saleExcelItem.getTaxType()) {
                        case "1":
                            str = "应税内含";
                            break;
                        case "2":
                            str = "应税外加";
                            break;
                        case "3":
                            str = "零税率";
                            break;
                        case "4":
                            str = "免税";
                            break;
                        case "9":
                            str = "不计税";
                            break;
                    }
                    saleExcelItem.setTaxType(saleExcelItem.getTaxType() + "(" + str + ")");
                }
                // 单价含税
                if(StringUtils.isNotEmpty(saleExcelItem.getUnitPriceIncludesTax())) {
                    String str = "";
                    switch (saleExcelItem.getUnitPriceIncludesTax()) {
                        case "0":
                            str = "不含税";
                            break;
                        case "1":
                            str = "含税";
                            break;
                    }
                    saleExcelItem.setUnitPriceIncludesTax(saleExcelItem.getUnitPriceIncludesTax() + "(" + str + ")");
                }
                // 业务员
                if(StringUtils.isNotEmpty(saleExcelItem.getSalesMan())) {
                    Cmsmv cmsmv = cmsmvMapper.selectOne(new LambdaQueryWrapper<Cmsmv>().eq(Cmsmv::getMv001, saleExcelItem.getSalesMan()));
                    saleExcelItem.setSalesMan(saleExcelItem.getSalesMan() + "(" + cmsmv.getMv002().trim() + ")");
                }
                // 销售部门
                if(StringUtils.isNotEmpty(saleExcelItem.getSalesDepartment())) {
                    Cmsme cmsme = cmsmeMapper.selectOne(new LambdaQueryWrapper<Cmsme>()
                            .eq(Cmsme::getMe001, saleExcelItem.getSalesDepartment()));
                    saleExcelItem.setSalesDepartment(saleExcelItem.getSalesDepartment() + "(" + cmsme.getMe002().trim() + ")");
                }
                // 付款条件
                if(StringUtils.isNotEmpty(saleExcelItem.getPaymentTerms())) {
                    List<Cmsna> cmsnas = cmsnaMapper.selectBusiness(saleExcelItem.getPaymentTerms());
                    if(cmsnas != null && cmsnas.size() == 1) {
                        saleExcelItem.setPaymentTerms(saleExcelItem.getPaymentTerms() + "(" + cmsnas.get(0).getNa003().trim() + ")");
                    }
                }
                // 发票类型
                if(StringUtils.isNotEmpty(saleExcelItem.getInvoiceType())) {
                    String str = "";
                    switch (saleExcelItem.getInvoiceType()) {
                        case "A":
                            str = "专用发票";
                            break;
                        case "B":
                            str = "普通发票";
                            break;
                        case "C":
                            str = "其他";
                            break;
                    }
                    saleExcelItem.setInvoiceType(saleExcelItem.getInvoiceType() + "(" + str + ")");
                }
            }

        }
    }
    // 判断字符串的内容是否相同
    private boolean isSameContent(String str, String str2) {
        if(str == null && str2 == null) return true;
        if(str == null || str2 == null) return false;
        return str.equals(str2);
    }

    public static List<List<SaleExcel>> mergeAndGroupSaleExcelList(List<List<SaleExcel>> nestedList, int groupSize) {
        Map<String, SaleExcel> mergedMap = new HashMap<>();

        for (List<SaleExcel> sublist : nestedList) {
            for (SaleExcel sale : sublist) {
                String key = sale.getCustomOrder();
                String key2 = sale.getHeadRemark();
                if (mergedMap.containsKey(key)&&!mergedMap.containsValue(key2)) {
                    // 合并的值
                    SaleExcel existingSale = mergedMap.get(key);
                    existingSale.setHeadRemark(existingSale.getHeadRemark() + sale.getHeadRemark());
                }else {
                    // 新的条目
                    mergedMap.put(key, sale);
                }
            }
        }

        // 将合并后的结果转换为列表
        List<SaleExcel> mergedList = new ArrayList<>(mergedMap.values());

        // 将合并后的列表分组
        List<List<SaleExcel>> groupedList = new ArrayList<>();
        for (int i = 0; i < mergedList.size(); i += groupSize) {
            int end = Math.min(i + groupSize, mergedList.size());
            groupedList.add(new ArrayList<>(mergedList.subList(i, end)));
        }

        return groupedList;
    }
}
